import time
from collections import OrderedDict
from datetime import datetime, timedelta
from types import FunctionType

from django.db.models import Sum, F
from django.http import JsonResponse
from django.shortcuts import render
from django.shortcuts import reverse
from django.utils.safestring import mark_safe

from web import models
from web.utils.group import get_incomma_value
from web.utils.pager import Pagernation


def get_total_warning_count(text, field):
    """
    获取choice字段的文本
    :param text: choice字段的名称
    :param field: choice字段
    :return:
    """

    def inner(obj=None, is_header=None, *args, **kwargs):
        if is_header:
            return text

        record_url = reverse('botgate_warnlog_list', kwargs={'pk': obj.id})
        tpl = '<a class="btn btn-info" href="{}">{:,}</a>'.format(record_url, obj.total_warning_count())

        return mark_safe(tpl)

    return inner


def get_total_inject_count(text, field):
    """
    获取choice字段的文本
    :param text: choice字段的名称
    :param field: choice字段
    :return:
    """

    def inner(obj=None, is_header=None, *args, **kwargs):
        if is_header:
            return text

        record_url = reverse('inject_attacktype_list', kwargs={'pk': obj.id})
        tpl = '<a class="btn btn-info" href="{}">{:,}</a>'.format(record_url, obj.total_inject_count())

        return mark_safe(tpl)

    return inner


def get_abnormal_request_count(text, field):
    """
    获取choice字段的文本
    :param text: choice字段的名称
    :param field: choice字段
    :return:
    """

    def inner(obj=None, is_header=None, *args, **kwargs):
        if is_header:
            return text
        date_time = obj.create_datetime
        abnormal_request_count = getattr(obj, field)
        record_url = reverse('botgate_attacktype_list', kwargs={'pk': obj.id})
        tpl = '<a class="btn btn-info" href="{}">{:,}</a>'.format(record_url, abnormal_request_count)
        return mark_safe(tpl)

    return inner


def display_attackip(obj=None, is_header=None, *args, **kwargs):
    """
    显示恶意IP数量
    :param obj:
    :param is_header:
    :param args:
    :param kwargs:
    :return:
    """
    if is_header:
        return "恶意IP"
    date_time = obj.create_datetime

    attackip_count = models.BotgateAttackIp.objects.filter(create_datetime__year=date_time.year,
                                                           create_datetime__month=date_time.month,
                                                           create_datetime__day=date_time.day).count()

    record_url = reverse('botgate_attackip_list', kwargs={'pk': obj.id})
    return mark_safe("<a class='btn btn-info' href='%s'>恶意IP(%s)</a>" % (record_url, attackip_count))


def display_attackpath(obj=None, is_header=None, *args, **kwargs):
    """
    显示恶意IP数量
    :param obj:
    :param is_header:
    :param args:
    :param kwargs:
    :return:
    """
    if is_header:
        return "攻击url"
    record_url = reverse('botgate_attackpath_list', kwargs={'pk': obj.id})
    return mark_safe("<a class='btn btn-info' href='%s'>攻击路径</a>" % (record_url))


def get_normal_request_count(text, field):
    """
    获取choice字段的文本
    :param text: choice字段的名称
    :param field: choice字段
    :return:
    """

    def inner(obj=None, is_header=None, *args, **kwargs):
        if is_header:
            return text

        record_url = reverse('botgate_website_list', kwargs={'pk': obj.id})
        tpl = '<a class="btn btn-info" href="{}">{:,}</a>'.format(record_url, obj.normal_request_count())

        return mark_safe(tpl)

    return inner


def get_ndaytype_count(text, field):
    """
    获取choice字段的文本
    :param text: choice字段的名称
    :param field: choice字段
    :return:
    """

    def inner(obj=None, is_header=None, *args, **kwargs):
        if is_header:
            return text

        record_url = reverse('botgate_ndaytype_list', kwargs={'pk': obj.id})
        tpl = '<a class="btn btn-info" href="{}">{:,}</a>'.format(record_url, obj.nday_count)

        return mark_safe(tpl)

    return inner


def get_bottype_count(text, field):
    """
    获取choice字段的文本
    :param text: choice字段的名称
    :param field: choice字段
    :return:
    """

    def inner(obj=None, is_header=None, *args, **kwargs):
        if is_header:
            return text

        record_url = reverse('botgate_bottype_list', kwargs={'pk': obj.id})
        tpl = '<a class="btn btn-info" href="{}">{:,}</a>'.format(record_url, obj.bot_count)

        return mark_safe(tpl)

    return inner


def botgate_list(request):
    list_display = [
        get_normal_request_count('正常请求数', 'request_count'),
        get_abnormal_request_count('异常请求数', 'abnormal_request_count'),
        get_total_warning_count('告警事件数', 'total_warning_count'),
        'replay_attack_count',
        'no_cookie_count',
        'invalid_token_count',
        get_bottype_count('高级自动化工具', 'bot_count'),
        get_total_inject_count('漏洞攻击', 'total_inject_count'),
        get_ndaytype_count('Nday攻击', 'nday_count'),
        'scan_count',
        display_attackip,
        display_attackpath,
        'update_datetime',
    ]
    queryset = models.Botgate.objects.all().order_by('-create_datetime')
    model_class = models.Botgate
    pager = Pagernation(request, queryset)
    # 1.处理表头
    header_list = []
    if list_display:
        for key_or_func in list_display:
            if isinstance(key_or_func, FunctionType):
                header_list.append(key_or_func(None, True))
            else:
                verbose_name = model_class._meta.get_field(key_or_func).verbose_name
                header_list.append(verbose_name)
    else:
        header_list.append(model_class._meta.model_name)
    # 2.处理表格内容
    data_list = queryset[pager.start:pager.end]
    body_list = []
    for row in data_list:
        tr_list = []
        if list_display:
            for key_or_func in list_display:
                if isinstance(key_or_func, FunctionType):
                    tr_list.append(key_or_func(row, False))
                else:
                    tr_list.append('' if getattr(row, key_or_func) == None else getattr(row, key_or_func))
        else:
            tr_list.append(row)
        body_list.append(tr_list)

    context = {
        'body_list': body_list,
        'header_list': header_list,
        'pager': pager,
    }
    return render(request, 'botgate_list.html', context)


def get_data_dict(field, field_name):
    today = datetime.now().date() + timedelta(days=1)
    date_dict = OrderedDict()
    for i in range(0, 30):
        date = today - timedelta(days=i)
        date_dict[date.strftime("%Y-%m-%d")] = [time.mktime(date.timetuple()) * 1000, 0]
    if field == 'normal_request_count':
        queryset = models.Botgate.objects.filter(create_datetime__gt=today - timedelta(days=29)).extra(
            select={'ctime': "DATE_FORMAT(web_botgate.create_datetime,'%%Y-%%m-%%d')"}).values('ctime').annotate(
            ct=Sum(F('request_count') - F('abnormal_request_count')))
        for item in queryset:
            date_dict[item['ctime']][1] = item['ct']
    else:
        queryset = models.Botgate.objects.filter(create_datetime__gt=today - timedelta(days=29)).extra(
            select={'ctime': "DATE_FORMAT(web_botgate.create_datetime,'%%Y-%%m-%%d')"}).values('ctime').annotate(
            ct=Sum(field))
        for item in queryset:
            date_dict[item['ctime']][1] = item['ct']
    return {'name': field_name, 'data': list(date_dict.values())}


def botgate_account_chart(request):
    account_mapping = {'request_count': '总请求数',
                       'normal_request_count': '正常请求数',
                       'abnormal_request_count': '异常请求数',
                       'high_warning_count': '高风险告警数',
                       'middle_warning_count': '中风险高警数'
                       }
    data_list = []
    for k, v in account_mapping.items():
        data_list.append(get_data_dict(k, v))
    return JsonResponse({'status': True, 'data': data_list})
